package com.wwdx.utils.math;

import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * @author liguoliang
 * @date 2018/6/15 19:28
 */
public abstract class AbstractCalculation {

    BigDecimal amount;
    private int scale = 2;
    private RoundingMode mode = RoundingMode.HALF_EVEN;

    AbstractCalculation(BigDecimal amount) {
        this.amount = amount;
    }

    AbstractCalculation(BigDecimal amount,int scale) {
        this(amount);
        this.scale = scale;
    }

    AbstractCalculation(BigDecimal amount,int scale,RoundingMode mode) {
        this(amount,scale);
        this.mode = mode;
    }

    AbstractCalculation(String value) {
        BigDecimalStringChecker.check(value);
        this.amount = new BigDecimal(value);
    }

    AbstractCalculation(String value,int scale) {
        this(value);
        this.scale = scale;
    }

    AbstractCalculation(String value,int scale,RoundingMode mode) {
        this(value,scale);
        this.mode = mode;
    }

    AbstractCalculation(double value) {
        this.amount = BigDecimal.valueOf(value);
    }

    AbstractCalculation(double value,int scale) {
        this(value);
        this.scale = scale;
    }

    AbstractCalculation(double value,int scale,RoundingMode mode) {
        this(value,scale);
        this.mode = mode;
    }

    AbstractCalculation(long value) {
        this.amount = BigDecimal.valueOf(value);
    }

    AbstractCalculation(long value,int scale) {
        this(value);
        this.scale = scale;
    }

    AbstractCalculation(long value,int scale,RoundingMode mode) {
        this(value,scale);
        this.mode = mode;
    }

    protected AbstractCalculation add(BigDecimal bigDecimal){
        this.amount = this.amount.add(bigDecimal).setScale(this.scale,this.mode);
        return this;
    }

    protected AbstractCalculation add(String value){
        this.amount = this.amount.add(new BigDecimal(value)).setScale(this.scale,this.mode);
        return this;
    }

    protected AbstractCalculation add(double value){
        this.amount = this.amount.add(BigDecimal.valueOf(value)).setScale(this.scale,this.mode);
        return this;
    }

    protected AbstractCalculation add(long value){
        this.amount = this.amount.add(BigDecimal.valueOf(value)).setScale(this.scale,this.mode);
        return this;
    }

    protected AbstractCalculation subtract(BigDecimal bigDecimal){
        this.amount = this.amount.subtract(bigDecimal).setScale(scale,mode);
        return this;
    }

    protected AbstractCalculation subtract(String value){
        this.amount = this.amount.subtract(new BigDecimal(value)).setScale(scale,mode);
        return this;
    }

    protected AbstractCalculation subtract(double value){
        this.amount = this.amount.subtract(BigDecimal.valueOf(value)).setScale(scale,mode);
        return this;
    }

    protected AbstractCalculation subtract(long value){
        this.amount = this.amount.subtract(BigDecimal.valueOf(value)).setScale(scale,mode);
        return this;
    }

    protected AbstractCalculation multiply(BigDecimal bigDecimal){
        this.amount = this.amount.multiply(bigDecimal).setScale(scale,mode);
        return this;
    }

    protected AbstractCalculation multiply(String value){
        this.amount = this.amount.multiply(new BigDecimal(value)).setScale(scale,mode);
        return this;
    }

    protected AbstractCalculation multiply(double value){
        this.amount = this.amount.multiply(BigDecimal.valueOf(value)).setScale(scale,mode);
        return this;
    }

    protected AbstractCalculation multiply(long value){
        this.amount = this.amount.multiply(BigDecimal.valueOf(value)).setScale(scale,mode);
        return this;
    }

    protected AbstractCalculation div(BigDecimal bigDecimal){
        this.amount = this.amount.divide(bigDecimal, scale,mode);
        return this;
    }

    protected AbstractCalculation div(String value){
        this.amount = this.amount.divide(new BigDecimal(value), scale,mode);
        return this;
    }

    protected AbstractCalculation div(double value){
        this.amount = this.amount.divide(BigDecimal.valueOf(value), scale,mode);
        return this;
    }

    protected AbstractCalculation div(long value){
        this.amount = this.amount.divide(BigDecimal.valueOf(value), scale,mode);
        return this;
    }

    /**
     * 获取BigDecimal实例
     * @return BigDecimal
     */
    protected abstract BigDecimal getBigDecimal();
}